package db

import (
	"errors"
	"fmt"
	"log"
	"os"
	"sync"
	"time"

	options2 "dubbo-go-app/pkg/config"
	v1 "dubbo-go-app/pkg/internal/data/v1"

	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
)

var (
	dbFactory v1.DataFactory
	once      sync.Once
)

type mysqlFactory struct {
	db *gorm.DB
}

func (m *mysqlFactory) Activity() v1.ActivityStore {
	return newActivitys(m)
}

func (m *mysqlFactory) Begin() *gorm.DB {
	return m.db.Begin()
}

var _ v1.DataFactory = &mysqlFactory{}

// 这个方法应该返回的是全局的一个变量，如果一开始的时候没有初始化好，那么就初始化一次，后续呢直接拿到这个变量
// 单例模式  演进成 sync.Once
func GetDBFactoryOr(mysqlOpts *options2.MySQLOptions) (v1.DataFactory, error) {
	if mysqlOpts == nil && dbFactory == nil {
		return nil, fmt.Errorf("failed to get mysql store fatory")
	}
	var errs error
	once.Do(func() {
		newLogger := logger.New(
			log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer（日志输出的目标，前缀和日志包含的内容——译者注）
			logger.Config{
				SlowThreshold: time.Second, // 慢 SQL 阈值
				//LogLevel:      logger.Info, // 日志级别
				LogLevel: logger.Info, // 日志级别
				//IgnoreRecordNotFoundError: true,        // 忽略ErrRecordNotFound（记录未找到）错误
				Colorful: true, // 禁用彩色打印
			},
		)
		dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=True&loc=Local",
			mysqlOpts.Activityname,
			mysqlOpts.Password,
			mysqlOpts.Host,
			mysqlOpts.Port,
			mysqlOpts.Database)
		db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{Logger: newLogger})
		if err != nil {
			return
		}
		sqlDB, _ := db.DB()
		dbFactory = &mysqlFactory{
			db: db,
		}
		//允许连接多少个mysql
		sqlDB.SetMaxOpenConns(mysqlOpts.MaxOpenConnections)
		//允许最大的空闲的连接数
		sqlDB.SetMaxIdleConns(mysqlOpts.MaxIdleConnections)
		//重用连接的最大时长
		sqlDB.SetConnMaxLifetime(mysqlOpts.MaxConnectionLifetime)
	})
	if dbFactory == nil || errs != nil {
		return nil, errors.New("failed to get mysql store factory")
	}
	return dbFactory, nil
}
